/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package games;

import java.util.ArrayList;
import java.lang.Integer;
import games.FourInARowState.FourInARowMove;
import java.util.Iterator;
import minmax.GameOutcome;
import minmax.GameState;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;

/**
 *
 * @author Mikael
 */
public class FourInARowStateTest {
    
    public FourInARowStateTest() {
    }

    @BeforeClass
    public static void setUpClass() throws Exception {
    }

    @AfterClass
    public static void tearDownClass() throws Exception {
    }
    
    @Before
    public void setUp() {
    }
    
    @After
    public void tearDown() {
    }

    @Test
    public void testMove() {
        System.out.println("move");
        FourInARowMove step = null;
        FourInARowState instance = new FourInARowState();
        instance.move(step);
        // TODO review the generated test code and remove the default call to fail.
        fail("The test case is a prototype.");
    }

    @Test
    public void testBacktrack() {
        System.out.println("backtrack");
        FourInARowState instance = new FourInARowState();
        instance.backtrack();
        // TODO review the generated test code and remove the default call to fail.
        fail("The test case is a prototype.");
    }

    @Test
    public void testMoves() {
        FourInARowState state = new FourInARowState();
        state.move(new FourInARowMove(false, 0, 0));
        state.move(new FourInARowMove(true, 1, 0));
        state.move(new FourInARowMove(false, 0, 1));
        state.move(new FourInARowMove(true, 2, 0));
        state.move(new FourInARowMove(false, 0, 2));
        state.move(new FourInARowMove(true, 0, 3));
        state.move(new FourInARowMove(false, 3, 0));
        state.move(new FourInARowMove(true, 1, 1));
        
        state.move(new FourInARowMove(false, 1, 2));
        state.move(new FourInARowMove(true, 2, 1));
        state.move(new FourInARowMove(false, 3, 1));
        state.move(new FourInARowMove(true, 2, 2));
        state.move(new FourInARowMove(false, 3, 2));
        
        
        
        FourInARowState instance = new FourInARowState();
        Iterator expResult = null;
        Iterator<FourInARowMove> result = state.moves();
        ArrayList<FourInARowMove> moves = new ArrayList<FourInARowMove>();
        while(result.hasNext()){
            FourInARowMove step = result.next();
            moves.add(step);
            System.out.println(step.toString());
        }
        
        assertEquals(7, moves.size());
        //assertEquals(0, moves.get(0).);
    }
    
    @Test
    public void testMoves_whenXIsAboutToWin() {
        /*
         * 
         * | |x| 
         * | |x|     
         * |o|x|o|
         */
        
        FourInARowState state = new FourInARowState();
        state.move(new FourInARowMove(false, 1, 0));
        state.move(new FourInARowMove(true, 0, 0));
        state.move(new FourInARowMove(false, 1, 1));
        state.move(new FourInARowMove(true, 2, 0));
        state.move(new FourInARowMove(false, 1, 2));
        
        
        Iterator<FourInARowMove> result = state.moves();
        ArrayList<FourInARowMove> moves = new ArrayList<FourInARowMove>();
        while(result.hasNext()){
            FourInARowMove step = result.next();
            moves.add(step);
            System.out.println(step.toString());
        }
        
        assertEquals(7, moves.size());
        int[] bits = new int[]{7,22,9,3,4,5,6};
        for (int i = 0; i < moves.size(); i++) {
            
            assertEquals(moves.get(i).getBit(), bits[i]);
        }
        //assertEquals(0, moves.get(0).);
    }
    
    @Test
    public void testOutcome_whenXHasForInARow() {
        /*
         * | |x|
         * | |x| 
         * |o|x|     
         * |o|x|o|
         */
        
        FourInARowState state = new FourInARowState();
        state.move(new FourInARowMove(false, 1, 0));
        state.move(new FourInARowMove(true, 0, 0));
        state.move(new FourInARowMove(false, 1, 1));
        state.move(new FourInARowMove(true, 2, 0));
        state.move(new FourInARowMove(false, 1, 2));
        state.move(new FourInARowMove(true, 0, 1));
        state.move(new FourInARowMove(false, 1, 3));
        
        GameOutcome outcome = state.outcome();
        assertEquals(false, outcome.player());
    }
    
    @Test
    public void testOutcome_whenXHasForInARow2() {
        /*
         * 
         * | |o|o|o
         * |x|x|x|x
         * |o|o|x|o
         * |x|x|o|o
         * |o|x|x|x     
         * |o|x|o|x
         */
        
        FourInARowState state = new FourInARowState();
        state.move(new FourInARowMove(false, 1, 0)); //x
        state.move(new FourInARowMove(true, 0, 0));
        state.move(new FourInARowMove(false, 1, 1));//x
        state.move(new FourInARowMove(true, 0, 1));
        state.move(new FourInARowMove(false, 1, 2));//x
        state.move(new FourInARowMove(true, 1, 3));
        state.move(new FourInARowMove(false, 0, 2));//x
        state.move(new FourInARowMove(true, 0, 3));
        
        /*|o|o|
        * |x|x|
        * |o|x|     
        * |o|x|
        */
        
        state.move(new FourInARowMove(false, 3, 0));//x
        state.move(new FourInARowMove(true, 2, 0));
        state.move(new FourInARowMove(false, 3, 1));//x
        state.move(new FourInARowMove(true, 3, 2));
        state.move(new FourInARowMove(false, 2, 1));//x
        state.move(new FourInARowMove(true, 2, 2));
        state.move(new FourInARowMove(false, 2, 3));//x
        state.move(new FourInARowMove(true, 3, 3));
        
        /*
             | | | | | | 
             | | | | | | 
            0|0|X|0| | | 
            X|X|0|0| | | 
            0|X|X|X| | | 
            0|X|0|X| | | 
         */
        
        state.move(new FourInARowMove(false, 3, 4));//x
        state.move(new FourInARowMove(true, 3, 5));
        state.move(new FourInARowMove(false, 2, 4));//x
        state.move(new FourInARowMove(true, 2, 5));
        state.move(new FourInARowMove(false, 1, 4));//x
        state.move(new FourInARowMove(true, 1, 5));
        state.move(new FourInARowMove(false, 0, 4));//x
        
        /*
          |0|0|0| | | 
         X|X|X|X| | | 
         0|0|X|0| | | 
         X|X|0|0| | | 
         0|X|X|X| | | 
         0|X|0|X| | |  
         */
        
        GameOutcome outcome = state.outcome();
        assertEquals(false, outcome.player());
    }

    @Test
    public void testPlayer() {
        System.out.println("player");
        FourInARowState instance = new FourInARowState();
        boolean expResult = false;
        boolean result = instance.player();
        assertEquals(expResult, result);
        // TODO review the generated test code and remove the default call to fail.
        fail("The test case is a prototype.");
    }

    @Test
    public void testEvaluate() {
        FourInARowState state = new FourInARowState();
        state.move(new FourInARowMove(false, 6, 0));
        state.move(new FourInARowMove(true, 0, 0));
        state.move(new FourInARowMove(false, 1, 0));
        state.move(new FourInARowMove(true, 0, 1));
        state.move(new FourInARowMove(false, 2, 0));
        state.move(new FourInARowMove(true, 0, 2));
        state.move(new FourInARowMove(false, 3, 0));
        state.move(new FourInARowMove(true, 0, 3));
        
        System.out.println("evaluate");
        boolean maximize = true;
        FourInARowState instance = new FourInARowState();
        int expResult = Integer.MAX_VALUE;
        state.outcome();
        int result = state.evaluate(maximize);
        assertEquals(expResult, result);
    }
    
    @Test
    public void testEvaluate2() {
        FourInARowState state = new FourInARowState();
        state.move(new FourInARowMove(false, 0, 0));
        state.move(new FourInARowMove(true, 1, 0));
        state.move(new FourInARowMove(false, 0, 1));
        state.move(new FourInARowMove(true, 2, 0));
        state.move(new FourInARowMove(false, 0, 2));
        state.move(new FourInARowMove(true, 0, 3));
        state.move(new FourInARowMove(false, 3, 0));
        state.move(new FourInARowMove(true, 1, 1));
        
        state.move(new FourInARowMove(false, 1, 2));
        state.move(new FourInARowMove(true, 2, 1));
        state.move(new FourInARowMove(false, 3, 1));
        state.move(new FourInARowMove(true, 2, 2));
        state.move(new FourInARowMove(false, 3, 2));
        
        state.move(new FourInARowMove(true, 2, 3));
        
        
        System.out.println("evaluate");
        boolean maximize = true;
        FourInARowState instance = new FourInARowState();
        int expResult = Integer.MAX_VALUE;
        state.outcome();
        int result = state.evaluate(maximize);
        assertEquals(expResult, result);
    }

    @Test
    public void testIsFinished() {
        System.out.println("isFinished");
        FourInARowState instance = new FourInARowState();
        boolean expResult = false;
        boolean result = instance.isFinished();
        assertEquals(expResult, result);
        // TODO review the generated test code and remove the default call to fail.
        fail("The test case is a prototype.");
    }

    @Test
    public void testOutcome() {
        System.out.println("outcome");
        FourInARowState instance = new FourInARowState();
        GameOutcome expResult = null;
        GameOutcome result = instance.outcome();
        assertEquals(expResult, result);
        // TODO review the generated test code and remove the default call to fail.
        fail("The test case is a prototype.");
    }

    @Test
    public void testCell() {
        System.out.println("cell");
        int x = 0;
        int y = 0;
        FourInARowState instance = new FourInARowState();
        Boolean expResult = null;
        Boolean result = instance.cell(x, y);
        assertEquals(expResult, result);
        // TODO review the generated test code and remove the default call to fail.
        fail("The test case is a prototype.");
    }

    @Test
    public void testClone() {
        System.out.println("clone");
        FourInARowState instance = new FourInARowState();
        GameState expResult = null;
        GameState result = instance.clone();
        assertEquals(expResult, result);
        // TODO review the generated test code and remove the default call to fail.
        fail("The test case is a prototype.");
    }
}
